//******************************************************************************
//this code is protected by the GNU affero GPLv3
//author:Sylvain BERTRAND <sylvain.bertrand AT gmail dot com>
//                        <digital.ragnarok AT gmail dot com>
//******************************************************************************
#include "globals.h"

static s8 get_pointer(struct client *c,s32 seat_name,struct msg *m)
{
  if(m->req_dws<3){
    PERR("client(%d):fatal:seat(%d)::get_pointer request misses pointer_id\n",
                                                               c->so,seat_name);
    return LWL_ERR;
  }

  LOG_WIRE("client(%d):seat(%d)::get_pointer pointer_id=%u\n",c->so,seat_name,
                                                                     m->req[2]); 

  return seat_get_pointer(c,seat_name,m->req[2]);
}

static s8 get_keyboard(struct client *c,s32 seat_name,struct msg *m)
{
  if(m->req_dws<3){
    PERR("client(%d):fatal:seat(%d)::get_keyboard request misses keyboard_id\n",
                                                               c->so,seat_name);
    return LWL_ERR;
  }

  LOG_WIRE("client(%d):seat(%d)::get_keyboard keyboard_id=%u\n",c->so,seat_name,
                                                                     m->req[2]); 

  return seat_get_keyboard(c,seat_name,m->req[2]);
}

s8 wl_seat_req(struct client *c,s32 seat_name,struct msg *m)
{
  s8 r;
  switch(m->req_op){
  case WL_SEAT_GET_POINTER:
    r=get_pointer(c,seat_name,m);
    break;
  case WL_SEAT_GET_KEYBOARD:
    r=get_keyboard(c,seat_name,m);
    break;
  //XXX:WL_SET_GET_TOUCH not supported
  case WL_SEAT_CLOSE:
    LOG_WIRE("client(%d):seat(%d)::close registry_map_id=%u\n",c->so,
                                                           seat_name,m->req[0]); 
    r=registry_map_close(c,m->req[0]);
    break;
  default:
    PERR("client(%d):fatal:seat(%d):request unknown opcode %u\n",c->so,
                                                           seat_name,m->req_op);
    r=LWL_ERR;
  }
  return r;
}

#define EV_CAPABILITIES_DWS 3
s8 wl_seat_ev_capabilities(struct client *c,u32 seat_id,u32 capabilities)
{
  u32 ev[EV_CAPABILITIES_DWS];

  ev[0]=seat_id;
  u16 ev_sz=EV_CAPABILITIES_DWS*sizeof(u32);
  ev[1]=ev_sz<<15|WL_SEAT_CAPABILITIES;
  ev[2]=capabilities;

  struct io_vec iov;
  iov.base=&ev;
  iov.len=ev_sz;

  struct msg_hdr msg;
  memset(&msg,0,sizeof(msg));
  msg.iov=&iov;
  msg.iov_len=1;

  LOG_WIRE("client(%d):seat::capabilities seat_id=%u capabilities=0x%08x\n",
                                                    c->so,seat_id,capabilities);

  l r;
  while(1){r=sendmsg(c->so,&msg,0); if(r!=-EINTR) break;}

  if(ISERR(r)){
    PERR("client(%d):fatal(%ld):seat::capabilities unable to send event\n",
                                                                       c->so,r);
    r=LWL_ERR;goto exit;
  }

  if(r!=ev_sz){
    PERR("client(%d):fatal:seat::capabilities only %ld/%ld were sent\n",c->so,r,
                                                                         ev_sz);
    r=LWL_ERR;goto exit;
  }

  r=LWL_OK;

exit:
  return (s8)r;
}
